package com.ruoyi.business.config;

import feign.Logger;
import feign.Request;
import feign.Retryer;
import org.springframework.cloud.openfeign.FeignFormatterRegistrar;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.format.datetime.standard.DateTimeFormatterRegistrar;
import org.springframework.http.MediaType;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Feign全局配置类
 * 
 * 配置流程：
 * 1. 配置日志级别 - 用于调试和排查问题
 * 2. 配置重试策略 - 禁用Feign默认重试
 * 3. 配置超时时间 - 设置连接和读取超时
 * 4. 配置消息转换器 - 支持多种媒体类型
 * 5. 配置日期格式化 - 统一日期格式
 */
@Configuration
public class FeignConfig {
    
    /**
     * 步骤1: 配置Feign的日志级别
     * NONE: 不记录任何日志
     * BASIC: 仅记录请求方法、URL、响应状态码及执行时间
     * HEADERS: 记录BASIC级别的基础上，记录请求和响应的header
     * FULL: 记录请求和响应的header、body和元数据
     */
    @Bean
    public Logger.Level feignLoggerLevel() {
        return Logger.Level.FULL;
    }
    
    /**
     * 步骤2: 配置Feign的重试策略
     * 禁用重试机制，由统一异常处理器处理失败情况
     * 避免重试导致的数据一致性问题
     */
    @Bean
    public Retryer feignRetryer() {
        return Retryer.NEVER_RETRY;
    }
    
    /**
     * 步骤3: 配置Feign的超时时间
     * 连接超时：建立连接的最长等待时间
     * 读取超时：等待数据返回的最长等待时间
     */
    @Bean
    public Request.Options requestOptions() {
        // 连接超时10秒，读取超时10秒
        return new Request.Options(10000, 10000);
    }
    
    /**
     * 步骤4: 配置消息转换器
     * 支持多种媒体类型的响应，增强兼容性
     */
    @Bean
    public MappingJackson2HttpMessageConverter messageConverter() {
        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        List<MediaType> mediaTypes = new ArrayList<>();
        // 支持JSON格式
        mediaTypes.add(MediaType.APPLICATION_JSON);
        // 支持纯文本格式
        mediaTypes.add(MediaType.TEXT_PLAIN);
        // 支持HTML格式（某些API可能返回HTML）
        mediaTypes.add(MediaType.TEXT_HTML);
        converter.setSupportedMediaTypes(mediaTypes);
        return converter;
    }
    
    /**
     * 步骤5: 配置日期格式化
     * 使用ISO标准日期格式，确保日期序列化和反序列化的一致性
     */
    @Bean
    public FeignFormatterRegistrar dateFormatter() {
        return registry -> {
            DateTimeFormatterRegistrar registrar = new DateTimeFormatterRegistrar();
            registrar.setUseIsoFormat(true);
            registrar.registerFormatters(registry);
        };
    }
} 